<template>
    <div class="tree-container">
      <div class="tree-header" v-if="title">
        <span>{{ title }}</span>
        <div class="tree-tools" v-if="showNodeActions">
          <el-button type="primary" size="small" @click="addRootNode">新增根节点</el-button>
        </div>
      </div>
      <div class="tree-filter">
        <el-input
          v-model="treeFilterText"
          placeholder="输入关键字过滤"
          clearable
          prefix-icon="Search"
        />
      </div>
      <el-tree
        ref="templateTree"
        :data="treeData"
        :props="treeProps"
        :filter-node-method="filterNode"
        :default-expanded-keys="props.defaultExpandedKeys"
        :current-node-key="props.currentNodeKey"
        highlight-current
        node-key="id"
        v-model="model"
        @node-click="handleNodeClick"
        draggable
        @node-drop="handleNodeDrop"
        class="custom-tree"
      >
        <template #default="{ node, data }">
          <div class="tree-node">
            <span class="node-label">{{ node.label }}</span>
            <div class="node-actions" v-if="data.id !== null && props.showNodeActions">
              <el-tooltip content="添加子节点" placement="top" :hide-after="0">
                <el-button size="small" text type="primary" :icon="Plus" @click.stop="addChildNode(data)" />
              </el-tooltip>
              <el-tooltip content="编辑节点" placement="top" :hide-after="0">
                <el-button size="small" text type="primary" :icon="Edit" @click.stop="editNode(data)" />
              </el-tooltip>
              <el-tooltip content="上移" placement="top" :hide-after="0">
                <el-button size="small" text type="primary" :icon="ArrowUp" @click.stop="moveNodeUp(data)" />
              </el-tooltip>
              <el-tooltip content="下移" placement="top" :hide-after="0">
                <el-button size="small" text type="primary" :icon="ArrowDown" @click.stop="moveNodeDown(data)" />
              </el-tooltip>
              <el-tooltip content="删除节点" placement="top" :hide-after="0">
                <el-button
                  size="small"
                  text
                  type="danger"
                  :icon="Delete"
                  @click.stop="removeNode(node, data)"
                  :disabled="hasChildren(data)"
                />
              </el-tooltip>
            </div>
          </div>
        </template>
      </el-tree>
    </div>

    <!-- 树节点操作对话框 -->
    <el-dialog
      v-model="treeDialogVisible"
      :title="isEditNode ? '编辑节点' : '添加节点'"
      width="30%"
      @close="handleTreeDialogClose"
    >
      <el-form :model="treeNodeForm" :rules="treeNodeRules" ref="treeNodeFormRef" label-width="80px" status-icon>
        <el-form-item label="节点名称" prop="name">
          <el-input v-model="treeNodeForm.name" placeholder="请输入节点名称"></el-input>
        </el-form-item>
        <el-form-item label="排序号" prop="sortNum">
          <el-input-number v-model="treeNodeForm.sortNum" :min="0" :max="9999" placeholder="请输入排序号" style="width:100%"></el-input-number>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancelTreeDialog">取 消</el-button>
          <el-button type="primary" @click="submitTreeNodeForm">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </template>

  <script setup>
  import {ArrowDown, ArrowUp, Delete, Edit, Plus} from '@element-plus/icons-vue'
  import {onMounted, ref, watch} from "vue";
  import {ElMessage, ElMessageBox} from 'element-plus'
  import http from "@/utils/request";

  // 定义组件属性
  const props = defineProps({
    apiPrefix: {
      type: String,
      default: 'queryCatalog'
    },
    showNodeActions: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: ''
    },
    defaultExpandedKeys: {
      type: Array,
      default: () => []
    },
    currentNodeKey: {
      type: [String, Number],
      default: null
    },
    maxLevel: {
      type: Number,
      default: 3
    }
  });
  const model = defineModel()

  // 对外暴露的事件和属性
  const emit = defineEmits(['node-click']);

  // 树状结构相关数据和方法
  const templateTree = ref(null);
  const treeData = ref([]);
  const treeProps = {
    children: 'children',
    label: 'name'
  };
  const treeFilterText = ref('');
  const treeDialogVisible = ref(false);
  const isEditNode = ref(false);
  const currentNode = ref(null);
  const treeNodeForm = ref({
    id: null,
    name: '',
    code: '',
    parentId: null,
    parent: null,
    sortNum: 0
  });
  const treeNodeRules = {
    name: [
      { required: true, message: '请输入节点名称', trigger: 'blur' },
    ],
    code: [
      { required: true, message: '请输入节点代码', trigger: 'blur' },
    ],
    sortNum: [
      { required: true, message: '请输入排序号', trigger: 'blur' },
    ],
  };
  const treeNodeFormRef = ref(null);

  // 监听过滤文本变化
  watch(treeFilterText, (val) => {
    templateTree.value?.filter(val);
  });

  // 节点过滤方法
  const filterNode = (value, data) => {
    if (!value) return true;
    return data.name.toLowerCase().includes(value.toLowerCase());
  };

  // 获取树数据
  const getTreeData = async () => {
    try {
      // 使用项目现有的http请求方式
      let res = await http.post(`/${props.apiPrefix}/list`, {
        fetch: 1,
        depth: 1,
        sortField: "sortNum",
        sortMethod: "asc"
      });
      if (res.code === 200) {
        // 添加"全部"节点作为第一个节点
        treeData.value = [{
          id: null,
          name: '全部',
          children: []
        }, ...(res.data || [])];
      } else {
        ElMessage.error(res.msg || '获取分类数据失败');
      }
    } catch (error) {
      console.error('获取树数据失败:', error);
      ElMessage.error('获取分类数据失败');
    }
  };

  // 初始化获取树数据
  const initData = () => {
    getTreeData();
  };

  // 添加根节点
  const addRootNode = () => {
    isEditNode.value = false;
    // 重置表单数据
    treeNodeForm.id = null;
    treeNodeForm.name = '';
    treeNodeForm.code = '';
    treeNodeForm.parent = null;
    treeNodeForm.sortNum = 0;
    // 清除当前节点引用
    currentNode.value = null;
    treeDialogVisible.value = true;
  };

  // 添加子节点
  const addChildNode = (data) => {
    isEditNode.value = false;
    // 深拷贝父节点数据，避免直接引用
    // 重置表单数据
    treeNodeForm.value.id = null;
    treeNodeForm.value.name = '';
    treeNodeForm.value.code = '';
    treeNodeForm.value.parent = data.id;
    treeNodeForm.value.sortNum = 0;
    // 保存父节点引用
    currentNode.value = data;
    treeDialogVisible.value = true;
    // 下一帧重置表单验证
  };

  // 辅助函数：根据ID查找节点
  const findNodeById = (nodes, id) => {
    if (!nodes || nodes.length === 0) return null;

    for (const node of nodes) {
      if (node.id === id) return node;

      if (node.children && node.children.length > 0) {
        const found = findNodeById(node.children, id);
        if (found) return found;
      }
    }

    return null;
  };

  // 辅助函数：根据ID查找节点及其父节点
  const findNodeAndParentById = (nodes, id, parent = null) => {
    if (!nodes || nodes.length === 0) return null;

    for (const node of nodes) {
      if (node.id === id) {
        return { node, parent };
      }

      if (node.children && node.children.length > 0) {
        const result = findNodeAndParentById(node.children, id, node);
        if (result) return result;
      }
    }

    return null;
  };

  // 通过ID更新树节点属性的方法
  const updateTreeNodeById = (id, properties) => {
    const node = findNodeById(treeData.value, id);
    if (node) {
      Object.assign(node, properties);
      return true;
    }
    return false;
  };

  // 通过ID在树中查找并删除节点
  const removeTreeNodeById = (id) => {
    const result = findNodeAndParentById(treeData.value, id);
    if (!result) return false;

    const { node, parent } = result;

    // 如果是根节点
    if (!parent) {
      const index = treeData.value.findIndex(item => item.id === id);
      if (index !== -1) {
        treeData.value.splice(index, 1);
        return true;
      }
    }
    // 如果是子节点
    else if (parent.children) {
      const index = parent.children.findIndex(item => item.id === id);
      if (index !== -1) {
        parent.children.splice(index, 1);
        return true;
      }
    }

    return false;
  };

  // 编辑节点
  const editNode = (data) => {
    isEditNode.value = true;
    // 深拷贝节点数据，避免直接引用可能导致的问题
    const nodeData = JSON.parse(JSON.stringify(data));

    treeNodeForm.value.id = nodeData.id;
    treeNodeForm.value.name = nodeData.name;
    treeNodeForm.value.code = nodeData.code;
    treeNodeForm.value.sortNum = nodeData.sortNum || 0;

    // 保存当前编辑的节点数据
    currentNode.value = data;
    treeDialogVisible.value = true;
    // 下一帧重置表单验证
  };

  // 保存节点
  const submitTreeNodeForm = async () => {
    await treeNodeFormRef.value.validate(async (valid) => {
      if (valid) {
        try {
          const url = isEditNode.value
            ? `/${props.apiPrefix}/update`
            : `/${props.apiPrefix}/create`;

          // 创建一个新对象来发送，避免引用问题
          const formData = { ...treeNodeForm.value };

          // 使用项目现有的http请求方式
          let res = await http.post(url, formData);

          if (res.code === 200) {
            ElMessage.success(isEditNode.value ? '更新成功' : '添加成功');
            treeDialogVisible.value = false;

            // 清空表单数据，避免数据残留
            treeNodeForm.id = null;
            treeNodeForm.name = '';
            treeNodeForm.code = '';
            treeNodeForm.parentId = null;
            treeNodeForm.parent = null;
            treeNodeForm.sortNum = 0;

            if (currentNode.value){
              if (!currentNode.value.children){
                currentNode.value.children = [];
              }

              if(`/${props.apiPrefix}/update` === url){
                // 更新节点属性
                  const node = findNodeById(treeData.value, formData.id);
                  if (node) {
                    node.name= formData.name;
                  }
              } else {
                currentNode.value.children.push(res.data);
              }
            }else{
              await getTreeData();
            }
            currentNode.value = null;
          } else {
            ElMessage.error(res.msg || (isEditNode.value ? '更新失败' : '添加失败'));
          }
        } catch (error) {
          console.error('保存节点失败:', error);
          ElMessage.error(isEditNode.value ? '更新失败' : '添加失败');
        }
      }
    });
  };

  // 删除节点
  const removeNode = (node, data) => {
    ElMessageBox.confirm(`确定要删除 ${data.name} 吗?`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(async () => {
      try {
        // 使用项目现有的http请求方式
        let res = await http.post(`/${props.apiPrefix}/delete`, { id: data.id });

        if (res.code === 200) {
          ElMessage.success('删除成功');

          // 从树中移除节点
          removeTreeNodeById(data.id);
        } else {
          ElMessage.error(res.msg || '删除失败');
        }
      } catch (error) {
        console.error('删除节点失败:', error);
        ElMessage.error('删除失败');
      }
    }).catch(() => {});
  };

  // 检查节点是否有子节点
  const hasChildren = (data) => {
    return data.children && data.children.length > 0;
  };

  // 处理节点点击
  const handleNodeClick = (data) => {
    emit('node-click', data);
  };

  // 处理节点拖拽
  const handleNodeDrop = async (draggingNode, dropNode, dropType, ev) => {
    try {
      // 根据拖拽类型更新节点的父级和顺序
      const dragData = {
        id: draggingNode.data.id,
        targetId: dropNode.data.id,
        dropType: dropType
      };

      // 使用项目现有的http请求方式
      let res = await http.post(`/${props.apiPrefix}/move`, dragData);

      if (res.code === 200) {
        ElMessage.success('移动成功');
        await getTreeData();
      } else {
        ElMessage.error(res.msg || '移动失败');
        await getTreeData(); // 失败时重新加载，恢复原状态
      }
    } catch (error) {
      console.error('节点移动失败:', error);
      ElMessage.error('移动失败');
      await getTreeData(); // 失败时重新加载，恢复原状态
    }
  };

  // 上移节点
  const moveNodeUp = async (data) => {
    try {
      // 找到同级节点列表
      let siblingNodes = [];
      if (data.parent) {
        // 如果有父节点，找到父节点下的所有子节点
        const parentNode = findNodeById(treeData.value, data.parent);
        if (parentNode && parentNode.children) {
          siblingNodes = parentNode.children;
        }
      } else {
        // 如果是根节点，获取所有根节点
        siblingNodes = treeData.value;
      }

      // 先确保所有节点都有唯一的排序号（处理sortNum相同或为0的情况）
      const normalizedNodes = normalizeSortNumbers(siblingNodes);

      // 找到当前节点的索引
      const currentIndex = normalizedNodes.findIndex(node => node.id === data.id);
      if (currentIndex <= 0) {
        ElMessage.warning('已经是第一个节点，无法上移');
        return;
      }

      // 获取上一个节点
      const prevNode = normalizedNodes[currentIndex - 1];

      // 交换排序号
      const currentSortNum = normalizedNodes[currentIndex].sortNum;
      const prevSortNum = prevNode.sortNum;

      // 先更新当前节点
      let updateCurrent = await http.post(`/${props.apiPrefix}/update`, {
        id: data.id,
        sortNum: prevSortNum,
        name: data.name,
        code: data.code
      });

      if (updateCurrent.code !== 200) {
        ElMessage.error(updateCurrent.msg || '上移失败');
        return;
      }

      // 再更新前一个节点
      let updatePrev = await http.post(`/${props.apiPrefix}/update`, {
        id: prevNode.id,
        sortNum: currentSortNum,
        name: prevNode.name,
        code: prevNode.code
      });

      if (updatePrev.code === 200) {
        ElMessage.success('上移成功');
        await getTreeData(); // 刷新树数据
      } else {
        ElMessage.error(updatePrev.msg || '上移失败');
        // 如果第二次更新失败，需要将第一个节点还原
        await http.post(`/${props.apiPrefix}/update`, {
          id: data.id,
          sortNum: currentSortNum,
          name: data.name,
          code: data.code
        });
      }
    } catch (error) {
      console.error('节点上移失败:', error);
      ElMessage.error('上移失败');
    }
  };

  // 下移节点
  const moveNodeDown = async (data) => {
    try {
      // 找到同级节点列表
      let siblingNodes = [];
      if (data.parent) {
        // 如果有父节点，找到父节点下的所有子节点
        const parentNode = findNodeById(treeData.value, data.parent);
        if (parentNode && parentNode.children) {
          siblingNodes = parentNode.children;
        }
      } else {
        // 如果是根节点，获取所有根节点
        siblingNodes = treeData.value;
      }

      // 先确保所有节点都有唯一的排序号（处理sortNum相同或为0的情况）
      const normalizedNodes = normalizeSortNumbers(siblingNodes);

      // 找到当前节点的索引
      const currentIndex = normalizedNodes.findIndex(node => node.id === data.id);
      if (currentIndex === -1 || currentIndex >= normalizedNodes.length - 1) {
        ElMessage.warning('已经是最后一个节点，无法下移');
        return;
      }

      // 获取下一个节点
      const nextNode = normalizedNodes[currentIndex + 1];

      // 交换排序号
      const currentSortNum = normalizedNodes[currentIndex].sortNum;
      const nextSortNum = nextNode.sortNum;

      // 先更新当前节点
      let updateCurrent = await http.post(`/${props.apiPrefix}/update`, {
        id: data.id,
        sortNum: nextSortNum,
        name: data.name,
        code: data.code
      });

      if (updateCurrent.code !== 200) {
        ElMessage.error(updateCurrent.msg || '下移失败');
        return;
      }

      // 再更新下一个节点
      let updateNext = await http.post(`/${props.apiPrefix}/update`, {
        id: nextNode.id,
        sortNum: currentSortNum,
        name: nextNode.name,
        code: nextNode.code
      });

      if (updateNext.code === 200) {
        ElMessage.success('下移成功');
        await getTreeData(); // 刷新树数据
      } else {
        ElMessage.error(updateNext.msg || '下移失败');
        // 如果第二次更新失败，需要将第一个节点还原
        await http.post(`/${props.apiPrefix}/update`, {
          id: data.id,
          sortNum: currentSortNum,
          name: data.name,
          code: data.code
        });
      }
    } catch (error) {
      console.error('节点下移失败:', error);
      ElMessage.error('下移失败');
    }
  };

  // 为节点分配唯一的排序号
  const normalizeSortNumbers = (nodes) => {
    if (!nodes || nodes.length === 0) return [];

    // 先对节点按现有排序号排序（如果排序号相同或为0，则按照它们在数组中的顺序）
    const sortedNodes = [...nodes];
    sortedNodes.sort((a, b) => {
      // 如果a和b的sortNum都存在且不相等，则按sortNum排序
      if (a.sortNum && b.sortNum && a.sortNum !== b.sortNum) {
        return a.sortNum - b.sortNum;
      }
      // 否则保持原有顺序
      return 0;
    });

    // 为每个节点分配新的连续排序号（从1开始）
    const normalizedNodes = sortedNodes.map((node, index) => {
      return {
        ...node,
        sortNum: index + 1
      };
    });

    return normalizedNodes;
  };

  // 处理对话框关闭事件
  const handleTreeDialogClose = () => {
    // 清空表单数据
    treeNodeForm.id = null;
    treeNodeForm.name = '';
    treeNodeForm.code = '';
    treeNodeForm.parentId = null;
    treeNodeForm.parent = null;
    treeNodeForm.sortNum = 0;
    currentNode.value = null;
    // 重置表单验证
    treeNodeFormRef.value?.resetFields();
  };

  // 取消对话框
  const cancelTreeDialog = () => {
    treeDialogVisible.value = false;
    // 对话框关闭事件会处理清空表单
  };

  onMounted(()=>{
    getTreeData();
  })

  // 暴露方法给父组件使用
  defineExpose({
    initData,
    getTreeData
  });
  </script>

  <style scoped lang="scss">
  .tree-container {
    width: 280px;
    min-width: 200px; /* 降低最小宽度，更好地适应小屏幕 */
    max-width: 320px;
    border-right: 1px solid #ebeef5;
    padding: 0; /* 移除内边距 */
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden; /* 防止水平滚动条 */
    box-sizing: border-box; /* 确保padding不增加宽度 */
    background-color: #fff; /* 白色背景 */
  }

  .tree-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px; /* 调整内边距 */
    border-bottom: 1px solid #ebeef5;
    margin-bottom: 0; /* 移除底部间距 */
    min-width: 0; /* 允许子元素缩小 */
    width: 100%; /* 填充可用空间 */
    background-color: #fff; /* 白色背景 */
    box-sizing: border-box;
  }

  .tree-tools {
    display: flex;
    gap: 5px;
  }

  .tree-filter {
    margin: 12px 16px; /* 调整外边距 */
    padding: 0; /* 移除内边距 */
  }

  .custom-tree {
    width: 100%;
    overflow: hidden;
    background-color: #fff; /* 白色背景 */
    padding: 0 8px 8px 8px; /* 调整内边距 */
    flex: 1; /* 占满剩余空间 */
    overflow-y: auto; /* 内容过多时滚动 */
  }

  .tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 8px; /* 调整内边距 */
    min-width: 0; /* 允许内容在必要时缩小 */
    width: 100%; /* 确保宽度100% */
    border-radius: 4px; /* 圆角 */
    transition: background-color 0.3s ease; /* 只保留背景色过渡效果 */
    position: relative; /* 添加相对定位 */
  }

  .node-label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    margin-right: 5px;
    flex: 1;
    color: #606266; /* 文字颜色 */
    font-size: 14px; /* 字体大小 */
  }

  .node-actions {
    display: none; /* 默认隐藏操作按钮 */
    flex-shrink: 0;
    margin-left: auto;
    flex-wrap: nowrap;
    white-space: nowrap;
    background-color: transparent; /* 移除背景色 */
    border-radius: 4px; /* 圆角 */
    padding: 2px 4px; /* 内边距 */
    position: absolute; /* 绝对定位 */
    right: 8px; /* 右侧距离 */
    top: 50%; /* 垂直居中 */
    transform: translateY(-50%); /* 垂直居中 */
  }

  .tree-node:hover .node-actions {
    display: flex; /* 悬停时显示操作按钮 */
  }

  /* 使用深度选择器修改Element Plus树组件的样式 */
  :deep(.el-tree-node__content) {
    height: auto;
    min-height: 30px;
    padding: 4px 0;
    overflow: hidden;
    transition: background-color 0.3s ease;
  }

  :deep(.el-tree-node__content:hover) {
    background-color: #f5f7fa !important;
  }

  /* 拖拽节点时的样式 */
  :deep(.is-dragging) {
    background-color: #e6f1fc !important;
    color: #409eff;
    font-weight: bold;
    opacity: 0.8;
  }

  :deep(.is-dragging .node-label) {
    color: #409eff;
  }

  :deep(.is-drop-inner) {
    background-color: #f0f9eb !important;
    color: #67c23a;
    border: 1px dashed #67c23a !important;
  }

  :deep(.is-drop-inner>.el-tree-node__content) {
    background-color: #f0f9eb !important;
  }

  :deep(.el-tree__drop-indicator) {
    background-color: #409eff !important;
    height: 2px !important;
  }

  :deep(.el-tree-node.is-drop-inner>.el-tree-node__content .node-label) {
    color: #67c23a;
  }

  :deep(.el-tree) {
    width: auto !important;
    max-width: 100%;
  }

  :deep(.el-tree-node__children) {
    overflow: hidden;
  }

  :deep(.el-tree-node) {
    width: 100%;
    overflow: hidden !important;
  }

  /* 按钮样式优化 */
  :deep(.el-button--small) {
    padding: 2px;
    margin-left: 0;
    min-width: 22px;
  }

  :deep(.el-tooltip__trigger) {
    margin: 0 1px;
  }

  :deep(.el-button.is-text) {
    padding: 2px 3px;
  }

  /* 响应式设计 */
  @media (max-width: 320px) {
    .tree-tools {
      flex-direction: column;
      gap: 5px;
    }
  }

  @media (max-width: 300px) {
    .node-actions {
      position: absolute;
      right: 5px;
      background: white;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
      border-radius: 4px;
      padding: 2px;
      z-index: 10;
    }

    .node-label {
      max-width: 150px;
    }
  }
  </style>
